package org.avapir.snake;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Random;
import java.util.Vector;

import javax.swing.JFrame;

/**
 * 
 * @author Alpen Ditrix
 *
 */
public class Game extends Canvas implements Constants {

	private static final long serialVersionUID = -7370133206082892698L;

	protected static int aliveSnakesCounter;
	protected static int currentSPSMultiplier;
	protected static Vector<Food> food;
	public static Game game;
	private static boolean isRunning;
	private static String mainframe_name;
	private static int plays;
	private static int record;
	protected static Vector<Snake> snakes;
	protected static HashMap<String, Sprite> sprites;
	protected static int SPS;
	private static final long startTime = System.currentTimeMillis();
	private static long threshold;
	protected static int winner;

	public static Vector<Food> getFood() {
		return food;
	}

	public static Vector<Snake> getSnakes() {
		return snakes;
	}

	public static boolean isRunning() {
		return isRunning;
	}

	public static void main(String[] args) {
		game = new Game();
		game.setPreferredSize(new Dimension(Constants.WIDTH, Constants.HEIGHT));

		JFrame gFrame = new JFrame(Game.mainframe_name);
		gFrame.setVisible(true);
		gFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gFrame.setLayout(new BorderLayout());
		gFrame.add(game, BorderLayout.CENTER);
		gFrame.pack();
		gFrame.setResizable(false);

		Game.start();
	}

	public static void restart() {
		// TODO
	}

	private static void letsRock() {
		while (isRunning) {
			threshold = 1000 / SPS;
			long enterTime = System.currentTimeMillis();
			// startTime = new Long(System.currentTimeMillis());
			update();
			Painter.render();
			if (debugMode) {

				Debug.workTime = System.currentTimeMillis() - enterTime;
				long sleepTime = threshold - Debug.workTime;

				try {
					if (sleepTime > 0) {
						Thread.sleep(sleepTime);
						Debug.longSleepsCounter++;
					} else {
						Debug.shortSleepsCounter++;
						Thread.sleep(10);
					}
				} catch (Exception e) {
				}
			} else {

				long sleepTime = threshold
						- (System.currentTimeMillis() - enterTime);
				try {
					if (sleepTime > 0) {
						Thread.sleep(sleepTime);
						Debug.longSleepsCounter++;
					} else {
						Debug.shortSleepsCounter++;
						Thread.sleep(10);
					}
				} catch (Exception e) {
				}
			}
		}
	}

	private static void start() {
		if (plays < 1)
			System.out.println("Starting new game...");
		else
			System.out.println("Restarting " + "game...");
		isRunning = true;
		Loader.initialization();
		letsRock();
	}

	// public static void forceWin(int winner){
	// stop(winner);
	// }

	private static void update() {
		/* ErlyVer */
		if (snakes.size() > 4)
			throw new RuntimeException(
					"It's not permitted to have more than 4 snakes! It's law! U must obey it, sucker!");
		if ((System.currentTimeMillis() - startTime)
				/ MULTIPLIER_INCREASE_DELAY + 3 > currentSPSMultiplier) {
			currentSPSMultiplier++;
			SPS = 5 * currentSPSMultiplier;
		}

		System.out.println(aliveSnakesCounter);
		if (aliveSnakesCounter == 1) {
			for (int i = 0; i < SNAKES_AMOUNT; i++) {
				if (snakes.get(i).isAlive())
					Game.stop(i);
			}
		}

		int i = 0;
		for (Snake s : snakes) {
			if (s.getScore() >= WIN_SCORE) {
				Game.stop(i);
			}
		}

		for (Snake s : snakes) {
			if (s.isAlive())
				s.move();
		}

		for (Snake s : snakes) {
			if (s.isAlive())
				s.lunch();
		}
	}

	protected static void createFood() {
		food = new Vector<Food>();
		for (int i = 0; i < FOOD_AMOUNT; i++) {
			food.add(new Food());
		}
	}

	protected static void createSnakes() {
		snakes = new Vector<Snake>();
		Random r = new Random();
		for (int i = 0; i < SNAKES_AMOUNT; i++) {
			int xx = r.nextInt(Game.game.getWidth());
			int yy = r.nextInt(Game.game.getHeight() - 30) + 30;
			snakes.add(new Snake(xx - xx % CELL_SIZE, yy - yy % CELL_SIZE, 2));
		}
		aliveSnakesCounter = SNAKES_AMOUNT;
	}

	protected static void newGame() {
		plays++;
	}

	protected static void readRecordScore() {
		try {
			RandomAccessFile f = new RandomAccessFile(new File("res/record"),
					"r");
			f.readByte();
		} catch (Exception e) {
			record = 0;
		}
	}

	protected static void stop(int i) {
		isRunning = false;
		winner = i;
		Painter.render();

		int scoreOut = record;
		for (Snake s : snakes) {
			int sc = s.getScore();
			if (sc > scoreOut) {
				scoreOut = sc;
			}
			s.setDirection(Direction.STOP);
		}

		if (scoreOut != 0)
			try {
				RandomAccessFile f = new RandomAccessFile(
						new File("res/record"), "rw");
				System.out.println(scoreOut);
				System.out.println(Integer.toBinaryString(scoreOut));
				System.out.println(Integer.parseInt(Integer
						.toBinaryString(scoreOut)));
				f.writeByte(Integer.parseInt(Integer.toBinaryString(scoreOut)));
				f.close();
			} catch (Exception e) {
				e.printStackTrace(System.err);
			}
		while (true) {
		}
	}

	protected static void updateSpeed() {
		currentSPSMultiplier = 3;
		SPS = 5 * currentSPSMultiplier;
	}

}